package com.rustic.server.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.xy.base.server.po.SysAdmin;
import cn.xy.base.server.service.SysAdminService;
import cn.xy.commons.enums.DisableStatus;
import cn.xy.commons.exception.JzRuntimeException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rustic.server.dao.AttractionsDao;
import com.rustic.server.enums.CategoryType;
import com.rustic.server.enums.LinkType;
import com.rustic.server.po.Attractions;
import com.rustic.server.po.Category;
import com.rustic.server.po.Rustic;
import com.rustic.server.po.UserCollectionLink;
import com.rustic.server.po.UserLikeLink;
import com.rustic.server.query.AttractionsAdminListQuery;
import com.rustic.server.query.AttractionsUserListQuery;
import com.rustic.server.service.AttractionsService;
import com.rustic.server.service.CategoryService;
import com.rustic.server.service.RusticService;
import com.rustic.server.service.UserBrowseLinkService;
import com.rustic.server.service.UserCollectionLinkService;
import com.rustic.server.service.UserLikeLinkService;
import com.rustic.server.vo.AttractionsVO;
import com.rustic.server.vo.AttractionsWebVO;
import com.rustic.server.vo.list.AttractionsAdminListVO;
import com.rustic.server.vo.list.AttractionsWebListVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Attractions对应的服务类实现
 *
 * @author auto
 */

@Slf4j
@Service
public class AttractionsServiceImpl extends ServiceImpl<AttractionsDao, Attractions> implements AttractionsService {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RusticService rusticService;

    @Autowired
    private SysAdminService sysAdminService;

    @Autowired
    private UserLikeLinkService userLikeLinkService;

    @Autowired
    private UserCollectionLinkService userCollectionLinkService;

    @Autowired
    private UserBrowseLinkService userBrowseLinkService;

    @Override
    public List<Attractions> listByIdIn(List<Integer> idList) {
        if (CollUtil.isEmpty(idList)) {
            return new ArrayList<>();
        }
        return this.listByIds(idList);
    }

    @Override
    public Map<Integer, Attractions> mapByIdIn(List<Integer> idList) {
        List<Attractions> attractionsList = this.listByIdIn(idList);
        return attractionsList.stream().collect(Collectors.toMap(Attractions::getId, b -> b));
    }

    @Override
    public LambdaQueryWrapper<Attractions> toAdminListWrapper(AttractionsAdminListQuery query) {
        LambdaQueryWrapper<Attractions> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Attractions::getRusticId, query.getRusticId());
        queryWrapper.like(CharSequenceUtil.isNotEmpty(query.getName()), Attractions::getName, query.getName());
        queryWrapper.eq(query.getGrade() > 0, Attractions::getGrade, query.getGrade());
        queryWrapper.eq(query.getType() > 0, Attractions::getType, query.getType());
        queryWrapper.like(CharSequenceUtil.isNotEmpty(query.getFeature()), Attractions::getFeature, query.getFeature());
        queryWrapper.gt(query.getStartPublishTime() != null, Attractions::getPublishTime, query.getStartPublishTime());
        queryWrapper.lt(query.getEndPublishTime() != null, Attractions::getPublishTime, query.getEndPublishTime());
        queryWrapper.eq(query.getStatus() > 0, Attractions::getStatus, query.getStatus());
        queryWrapper.orderByDesc(Attractions::getSort);
        queryWrapper.orderByDesc(Attractions::getUpdateTime);
        return queryWrapper;
    }

    @Override
    public List<AttractionsAdminListVO> toAdminListVo(List<Attractions> attractionsList) {
        List<AttractionsAdminListVO> results = new ArrayList<>();
        // 获取分类
        List<Integer> categoryTypes = new ArrayList<>();
        categoryTypes.add(CategoryType.ATTRACTION_TYPE.getValue());
        categoryTypes.add(CategoryType.ATTRACTION_GRADE.getValue());
        List<Category> categoryList = categoryService.listByTypes(categoryTypes);
        Map<Integer, Category> categoryMap = categoryList.stream().collect(Collectors.toMap(Category::getId, b -> b));
        for (Attractions attractions : attractionsList) {
            AttractionsAdminListVO attractionsAdminListVO = new AttractionsAdminListVO(attractions);
            attractionsAdminListVO.setGradeName(categoryMap.get(attractions.getGrade()) != null ?
                    categoryMap.get(attractions.getGrade()).getName() : "");
            attractionsAdminListVO.setTypeName(categoryMap.get(attractions.getType()) != null ?
                    categoryMap.get(attractions.getType()).getName() : "");
            results.add(attractionsAdminListVO);
        }
        return results;
    }

    @Override
    public List<AttractionsWebListVO> toWebListVo(List<Attractions> attractionsList, int userId) {
        List<Integer> attractionsIdList = attractionsList.stream().map(Attractions::getId).collect(Collectors.toList());
        Map<Integer, Long> likeCountMap = userLikeLinkService.mapByTargetIdAndType(attractionsIdList, LinkType.ATTRACTIONS);
        Map<Integer, Long> collectionCountMap = userCollectionLinkService.mapByTargetIdAndType(attractionsIdList, LinkType.ATTRACTIONS);
        Map<Integer, Long> browseCountMap = userBrowseLinkService.mapByTargetIdAndType(attractionsIdList, LinkType.ATTRACTIONS);
        // 用户是否有点赞收藏
        Map<Integer, UserLikeLink> userLikeMap = userLikeLinkService.mapByUserTargetAndType(attractionsIdList, LinkType.ATTRACTIONS, userId);
        Map<Integer, UserCollectionLink> userCollectionMap = userCollectionLinkService.mapByUserTargetAndType
                (attractionsIdList, LinkType.ATTRACTIONS, userId);
        // 查询景点对应的乡村
        List<Integer> rusticIdList = attractionsList.stream().map(Attractions::getRusticId).collect(Collectors.toList());
        Map<Integer, Rustic> rusticMap = rusticService.mapByIdIn(rusticIdList);
        return attractionsList.stream().map(item -> {
            AttractionsWebListVO attractionsWebVO = new AttractionsWebListVO(item);
            // 得到点赞的数量
            if (likeCountMap.get(item.getId()) != null) {
                attractionsWebVO.setLikeCount(likeCountMap.get(item.getId()));
            }
            // 收藏的数量
            if (collectionCountMap.get(item.getId()) != null) {
                attractionsWebVO.setCollectionCount(collectionCountMap.get(item.getId()));
            }
            // 浏览数量
            if (browseCountMap.get(item.getId()) != null) {
                attractionsWebVO.setBrowseCount(browseCountMap.get(item.getId()));
            }
            // 用户是否点赞
            if (userLikeMap.get(item.getId()) != null) {
                attractionsWebVO.setLike(true);
            }
            // 用户是否收藏
            if (userCollectionMap.get(item.getId()) != null) {
                attractionsWebVO.setCollection(true);
            }
            // 填充对应的乡村名称
            Rustic rustic = rusticMap.get(item.getRusticId());
            if (rustic != null) {
                attractionsWebVO.setRusticName(rustic.getName());
            }
            return attractionsWebVO;
        }).collect(Collectors.toList());
    }

    @Override
    public LambdaQueryWrapper<Attractions> toWebListWrapper(AttractionsUserListQuery query) {
        LambdaQueryWrapper<Attractions> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(Attractions::getId, Attractions::getRusticId, Attractions::getName, Attractions::getAddress,
                Attractions::getDetailedAddress, Attractions::getCover, Attractions::getGrade, Attractions::getType,
                Attractions::getFeature, Attractions::getPrice, Attractions::getPublishTime, Attractions::getCreateTime,
                Attractions::getUpdateTime);
        queryWrapper.eq(query.getRusticId() > 0, Attractions::getRusticId, query.getRusticId());
        queryWrapper.like(CharSequenceUtil.isNotEmpty(query.getName()), Attractions::getName, query.getName());
        queryWrapper.like(CharSequenceUtil.isNotEmpty(query.getName()), Attractions::getAddress, query.getAddress());
        queryWrapper.eq(query.getType() > 0, Attractions::getType, query.getType());
        queryWrapper.eq(query.getGrade() > 0, Attractions::getGrade, query.getGrade());
        queryWrapper.eq(Attractions::getStatus, DisableStatus.NORMAL.getValue());
        queryWrapper.orderByDesc(Attractions::getSort);
        queryWrapper.orderByDesc(Attractions::getUpdateTime);
        return queryWrapper;
    }

    private void checkAddOrUpdate(Attractions attractions) {
        // 关联乡村是否存在
        Rustic rustic = rusticService.getById(attractions.getRusticId());
        if (rustic == null) {
            throw new JzRuntimeException(RusticService.RUSTIC_NOT_EXIST);
        }
        // 分类id是否存在
        Category category = categoryService.getByIdAndType(attractions.getType(), CategoryType.ATTRACTION_TYPE);
        if (category == null) {
            throw new JzRuntimeException(CategoryService.CATEGORY_NOT_EXIST);
        }
        // 景点等级是否存在
        if (attractions.getGrade() > 0) {
            Category categoryGrade = categoryService.getByIdAndType(attractions.getGrade(), CategoryType.ATTRACTION_GRADE);
            if (categoryGrade == null) {
                throw new JzRuntimeException("景点等级不存在!");
            }
        }

    }

    @Override
    public void add(Attractions attractions) {
        // 校验参数
        this.checkAddOrUpdate(attractions);
        // fixme 直接发布
        attractions.setStatus(DisableStatus.NORMAL.getValue());
        attractions.setPublishTime(new Date());
        this.save(attractions);
    }

    @Override
    public void updateAttractions(Attractions attractions) {
        // 校验参数
        Attractions getAttractions = this.getById(attractions.getId());
        if (getAttractions == null) {
            throw new JzRuntimeException(AttractionsService.ATTRACTIONS_NOT_EXIST);
        }
        this.checkAddOrUpdate(attractions);
        // fixme 直接发布
        attractions.setStatus(DisableStatus.NORMAL.getValue());
        attractions.setPublishTime(new Date());
        this.updateById(attractions);
    }

    @Override
    public AttractionsVO getDetailById(int id) {
        Attractions attractions = this.getById(id);
        if (attractions == null) {
            throw new JzRuntimeException(AttractionsService.ATTRACTIONS_NOT_EXIST);
        }
        AttractionsVO attractionsVO = new AttractionsVO(attractions);
        List<Integer> sysAdminListId = new ArrayList<>();
        Collections.addAll(sysAdminListId, attractions.getCreatorId(), attractions.getModifierId());
        Map<Integer, SysAdmin> sysAdminMap = sysAdminService.mapByIdList(sysAdminListId);
        attractionsVO.setModifier(sysAdminMap.get(attractions.getModifierId()) != null ?
                sysAdminMap.get(attractions.getModifierId()).getUsername() : "");
        attractionsVO.setCreator(sysAdminMap.get(attractions.getCreatorId()) != null ?
                sysAdminMap.get(attractions.getCreatorId()).getUsername() : "");
        return attractionsVO;
    }

    @Override
    public int enabled(int id) {
        Attractions attractions = this.getById(id);
        if (attractions == null) {
            throw new JzRuntimeException(AttractionsService.ATTRACTIONS_NOT_EXIST);
        }
        if (DisableStatus.isDisable(attractions.getStatus())) {
            // 原来为2的,要上架的
            attractions.setPublishTime(new Date());
        }
        attractions.setStatus(DisableStatus.negate(attractions.getStatus()));
        this.updateById(attractions);
        return attractions.getStatus();
    }

    @Override
    public AttractionsWebVO getByIdToWeb(int id) {
        Attractions attractions = this.getById(id);
        if (attractions == null) {
            throw new JzRuntimeException(AttractionsService.ATTRACTIONS_NOT_EXIST);
        }
        AttractionsWebVO attractionsVO = new AttractionsWebVO(attractions);
        // 获取分类
        List<Integer> categoryTypes = new ArrayList<>();
        categoryTypes.add(CategoryType.ATTRACTION_TYPE.getValue());
        categoryTypes.add(CategoryType.ATTRACTION_GRADE.getValue());
        List<Category> categoryList = categoryService.listByTypes(categoryTypes);
        Map<Integer, Category> categoryMap = categoryList.stream().collect(Collectors.toMap(Category::getId, b -> b));
        // 景点等级
        attractionsVO.setGradeName(categoryMap.get(attractions.getGrade()) != null ?
                categoryMap.get(attractions.getGrade()).getName() : "");
        // 景点类型
        attractionsVO.setTypeName(categoryMap.get(attractions.getType()) != null ?
                categoryMap.get(attractions.getType()).getName() : "");
        // 添加乡村名称
        Rustic rustic = rusticService.getById(attractions.getRusticId());
        attractionsVO.setRusticName(rustic != null ? rustic.getName() : "");
        return attractionsVO;
    }
}
